#pragma once

#include "includeBase.h"
#include "../common/BasePclModel.h"

class HypothesisVerificationModel : public BasePclModel
{
public:
    HypothesisVerificationModel();

public:
    static HypothesisVerificationModel& get();

public: // IJsonSerializable
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    QJsonObject toJson() const override;

public: // Property
    QString modelFile() const { return modelFile_; }
    void setModelFile(const QString& modelFile) { modelFile_ = modelFile; }

    QString sceneFile() const { return sceneFile_; }
    void setSceneFile(const QString& sceneFile) { sceneFile_ = sceneFile; }

    bool showKeypoints() const { return showKeypoints_; }
    void setShowKeypoints(bool showKeypoints)
    {
        showKeypoints_ = showKeypoints;
    }

    bool useHough() const { return useHough_; }
    void setUseHough(bool useHough) { useHough_ = useHough; }

    float modelSamplingSize() const { return modelSamplingSize_; }
    void setModelSamplingSize(float modelSamplingSize)
    {
        modelSamplingSize_ = modelSamplingSize;
    }

    float sceneSamplingSize() const { return sceneSamplingSize_; }
    void setSceneSamplingSize(float sceneSamplingSize)
    {
        sceneSamplingSize_ = sceneSamplingSize;
    }

    float lrfSupportRadius() const { return lrfSupportRadius_; }
    void setLrfSupportRadius(float lrfSupportRadius)
    {
        lrfSupportRadius_ = lrfSupportRadius;
    }

    float shotDescriptorRadius() const { return shotDescriptorRadius_; }
    void setShotDescriptorRadius(float shotDescriptorRadius)
    {
        this->shotDescriptorRadius_ = shotDescriptorRadius;
    }

    float clusteringBinSize() const { return clusteringBinSize_; }
    void setClusteringBinSize(float clusteringBinSize)
    {
        this->clusteringBinSize_ = clusteringBinSize;
    }

    float clusteringThresh() const { return clusteringThresh_; }
    void setClusteringThresh(float clusteringThresh)
    {
        clusteringThresh_ = clusteringThresh;
    }

    int icpMaxIter() const { return icp_max_iter_; }
    void setIcpMaxIter(int icpMaxIter) { icp_max_iter_ = icpMaxIter; }

    float icpCorrDistance() const { return icp_corr_distance_; }
    void setIcpCorrDistance(float icpCorrDistance)
    {
        icp_corr_distance_ = icpCorrDistance;
    }

    float hvResolution() const { return hv_resolution_; }
    void setHvResolution(float hvResolution) { hv_resolution_ = hvResolution; }

    float hvOccupancyGridResolution() const
    {
        return hv_occupancy_grid_resolution_;
    }
    void setHvOccupancyGridResolution(float hvOccupancyGridResolution)
    {
        hv_occupancy_grid_resolution_ = hvOccupancyGridResolution;
    }

    float hvClutterReg() const { return hv_clutter_reg_; }
    void setHvClutterReg(float hvClutterReg) { hv_clutter_reg_ = hvClutterReg; }

    float hvInlierTh() const { return hv_inlier_th_; }
    void setHvInlierTh(float hvInlierTh) { hv_inlier_th_ = hvInlierTh; }

    float hvOcclusionTh() const { return hv_occlusion_th_; }
    void setHvOcclusionTh(float hvOcclusionTh)
    {
        hv_occlusion_th_ = hvOcclusionTh;
    }

    float hvRadClutter() const { return hv_rad_clutter_; }
    void setHvRadClutter(float hvRadClutter) { hv_rad_clutter_ = hvRadClutter; }

    float hvRegularizer() const { return hv_regularizer_; }
    void setHvRegularizer(float hvRegularizer)
    {
        hv_regularizer_ = hvRegularizer;
    }

    float hvRadNormals() const { return hv_rad_normals_; }
    void setHvRadNormals(float hvRadNormals) { hv_rad_normals_ = hvRadNormals; }

    bool hvDetectClutter() const { return hv_detect_clutter_; }
    void setHvDetectClutter(bool hvDetectClutter)
    {
        hv_detect_clutter_ = hvDetectClutter;
    }

private:
    QString modelFile_ = "data/tutorials/correspondence_grouping/milk.pcd";
    QString sceneFile_ = "data/tutorials/correspondence_grouping/"
                         "milk_cartoon_all_small_clorox.pcd";

    // Algorithm params
    bool showKeypoints_ = true;
    bool useHough_ = false;
    float modelSamplingSize_ = 0.02f;
    float sceneSamplingSize_ = 0.02f;
    float lrfSupportRadius_ = 0.015f;
    float shotDescriptorRadius_ = 0.02f;
    float clusteringBinSize_ = 0.01f;
    float clusteringThresh_ = 5.0f;
    int icp_max_iter_ = 5;
    float icp_corr_distance_ = 0.005f;
    float hv_resolution_ = 0.005f;
    float hv_occupancy_grid_resolution_ = 0.01f;
    float hv_clutter_reg_ = 5.0f;
    float hv_inlier_th_ = 0.005f;
    float hv_occlusion_th_ = 0.01f;
    float hv_rad_clutter_ = 0.03f;
    float hv_regularizer_ = 3.0f;
    float hv_rad_normals_ = 0.05;
    bool hv_detect_clutter_ = true;
};
